iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
AI Engineering

Agent 開發, 從本地到雲端: AI 工程師的 K8s 筆記系列 第 18 篇

Day 18|Spot / Preemptible 的代價:開發機重開、自動還原失敗的實錄,on K8s 會怎麼不同

  • 分享至 

  • xImage
  •  

cover

POV:早上打開終端,Tailscale 連得上、docker ps 全綠,你鬆一口氣,然後 tmux attach 進去發現昨晚那幾個 agent session 的視窗只剩一半。

Day 01 開頭提過,這個系列開寫前一週,我的開發機重開了一次。今天把那次的完整經過寫下來,然後回答一個問題:如果這些東西是跑在 K8s 上,會有什麼不同?

先講那台機器:GCP 上的一台 Spot VM,我用它跑 OpenAB bot 艦隊(docker compose)、RAG 研究環境 devstack(也是 compose)、liaostudio(systemd),還有好幾個 AI agent 的終端 session,tmux 裡跑著 OMP 和 Claude Code。選 Spot 是為了省錢,代價是雲端隨時可以把它收回去,而且收回之後 VM 本身不會自動重開。

六月它被收回過一次,那次我有去查,確認是 preemption。九月這次我沒去查原因,只知道它重開了。

重開機那天發生的事

2026-09-07 08:58(UTC)。前一次開機是 09-04 12:20,撐了大約 2 天 20 小時;重開後 kernel 從 6.17 變成 7.0。之後三件事各自有不同的結局:

VM 本身:Cloud Scheduler 拉起來。 我有一個每 5 分鐘跑一次的 Cloud Scheduler job,看到 VM 是 TERMINATED 就把它 start 起來。這是 Day 17 講的那個獨立問題的解法。

Docker 容器:全自動回來。 OpenAB 容器跟 devstack 全套都是 restart: unless-stopped,靠 restart policy 自己起來,我什麼都沒做。9 月 15 日又重開了一次,我事後用 docker inspect 看 StartedAt:13 隻 OpenAB 容器全部在開機後 22 秒回來。Day 03 講 container 解決重啟這件事,這兩次算是實證。

tmux 裡的 agent session:部分還原失敗。 這是今天的重點。

還原失敗的細節

我有一套自己寫的還原腳本:每 15 分鐘快照一次 tmux 的 layout 和每個 pane 在跑什麼,開機時由 systemd 用最新快照重建。這次它跑了,結果是:

  1. 視窗塞不下。 開機時沒有任何終端 attach 在 tmux 上,tmux 用預設的 80x24 視窗尺寸。腳本切到第 5 個 pane 時 split-window 回 no space for new pane,後面的 pane 根本沒建出來。
  2. 好的快照被輪替掉了。 更糟的是,重開後那個每 15 分鐘的快照照常跑,它忠實記錄了壞掉的還原狀態;而快照只保留 5 份,重開前那份健康的很快就被推出去了。我要找回原本的 session,得從別的地方(agent 自己落盤的 JSONL)反查。

兩個問題,沒有一個是資料遺失,agent 的對話紀錄都持續寫在磁碟上。但「把東西拉回原本的樣子」這件事,靠我自己寫的腳本做,做失敗了。事後改了兩件事:無人值守還原前先把視窗尺寸設好;快照輪替要保護最後一次健康狀態,不能讓壞的把好的推掉。

如果這些是跑在 K8s 上

把三個結局對照一下:

  • Docker 容器那一類,在 K8s 上就是 Deployment:宣告 replicas,Pod 死了叢集補。這次 restart policy 做到了同樣的事;Deployment 多的是「有多個節點時,補回來的 Pod 可以落在別台機器」這個可能性,但那要看下一點的前提,單節點叢集上它跟 restart policy 差不多。
  • VM 被收回這件事,在 managed K8s 上會變成一個節點消失。叢集會試著把那個節點上的 Pod 排到其他節點,前提是你有其他節點、Pod 沒有綁死在特定機器上、而且叢集還有足夠資源。GKE 上用 Spot VM 當節點時,節點被收回前會先收到通知,Pod 有機會走 graceful termination。Kubernetes 官方把這類事件叫 disruption,但要分兩種:Spot 節點被收回是 involuntary,叢集擋不住;PodDisruptionBudget 管的是 voluntary,也就是升級、drain 這類叢集自己主動發起的驅逐,它能限制「同時最多拿掉幾個 Pod」,不能保護 Pod 不被 Spot 回收。單節點的 k3s 沒有這個好處,它跟我的 VM 一樣要等機器回來。
  • tmux session 還原這件事,K8s 沒有對應物。它不是一個容器,是一個互動式終端裡的長對話。這也是我還沒把開發環境搬上 K8s 的原因之一:K8s 擅長顧「無狀態、可重建」的工作負載,而我的 agent session 是有狀態的、重建等於重新對話。

我學到的

Spot 的代價不是「會被收回」,那是已知的。代價是:你以為會自動回來的東西,要真的重開一次才知道哪些回得來、哪些回不來。 容器回得來、VM 回得來、我自己寫的還原腳本有兩個洞。這次之後我改了腳本,但下次重開前,我不會知道改對了沒有。

明天把這些代價換算成錢:常駐 vs 按需、GPU 節點、egress,用一張表比較三種部署。

今日一句話

Spot 不是省錢的技巧,是一場定期的災難演練:宣告過的狀態(容器、Deployment)多半回得來,沒宣告的(終端裡的對話)要靠自己。

延伸閱讀


上一篇
Day 17|我的真實決策:評估 Cloud Run 後決定「暫不搬」— 評估表與理由(liaostudio)
系列文
Agent 開發, 從本地到雲端: AI 工程師的 K8s 筆記 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言